home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / gtlayout-source.lha / LT_Build.c < prev    next >
C/C++ Source or Header  |  1996-09-23  |  25KB  |  1,034 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1996 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. /*****************************************************************************/
  15.  
  16.  
  17. /****** gtlayout.library/LT_BuildA ******************************************
  18. *
  19. *   NAME
  20. *    LT_BuildA -- turn the user interface specs into a window
  21. *                 and gadgets.
  22. *
  23. *   SYNOPSIS
  24. *    Window = LT_BuildA(Handle,Tags);
  25. *      D0                 A0    A1
  26. *
  27. *    struct Window *LT_BuildA(LayoutHandle *,struct TagItem *);
  28. *
  29. *    Window = LT_Build(Handle,...);
  30. *
  31. *    struct Window *LT_Build(LayoutHandle *,...);
  32. *
  33. *   FUNCTION
  34. *    This is the big one. After building up a user interface specification
  35. *    using LT_NewA() a call to LT_BuildA() will finally lay out the single
  36. *    user interface elements, open a window and put the gadgets, etc.
  37. *    inside.
  38. *
  39. *    The code tries to fit all the gadgets into the window, but if it
  40. *    runs out of space it will fall back to a different font and
  41. *    rescale the user interface objects to match it. It will first
  42. *    fall back onto the system default font. If unsuccessful it will
  43. *    as a last resort try to use topaz.font/8.
  44. *
  45. *    To make it easier to distinguish between different handles that
  46. *    share the same Window->UserPort, the Window->UserData pointer
  47. *    will point to the LayoutHandle that created it (V13).
  48. *
  49. *        NOTE: Earlier library releases did not support this feature,
  50. *            so be prepared to deal with Window->UserData == NULL.
  51. *
  52. *   INPUTS
  53. *    Handle - Pointer to a LayoutHandle structure.
  54. *
  55. *    Tags - Pointer to TagItem list controlling window
  56. *        and layout attributes.
  57. *
  58. *
  59. *    All the tag values given are passed straight away to OpenWindowTags(),
  60. *    see intuition.doc for more information.
  61. *
  62. *    In addition to this a number of private tag values are supported:
  63. *
  64. *    LAWN_Menu (struct Menu *) - The menu to attach to the window. The
  65. *        IDCMP flags will be updated to include IDCMP_MENUPICK if this
  66. *        tag is used.
  67. *
  68. *    LAWN_MenuTemplate (struct NewMenu *) - A list of filled-in
  69. *        NewMenu structures which will get passed straight through
  70. *        to LT_NewMenuTemplate(). If a menu could be created, it will
  71. *        be attached to the window. LT_DeleteHandle() will then later
  72. *        automatically dispose of the menu. Please note that the window
  73. *        may fail to open due to the menu layout going wrong. Separate
  74. *        calls to LT_NewMenuTemplate() and LT_Build() may be a better
  75. *        approach since it is easier to find out which process went
  76. *        wrong. You will find a pointer to the menu attached to the
  77. *        LayoutHandle in LayoutHandle->Menu. Please note that this
  78. *        entry only exists in LayoutHandles created by gtlayout.library
  79. *        v13 or higher. (V13)
  80. *
  81. *            NOTE: This tag effectively overrides LAWN_Menu.
  82. *
  83. *    LAWN_MenuTags (struct TagItem *) - A list of TagItems which
  84. *        will get passed straight through to LT_NewMenuTagList().
  85. *        Even if you don't ask for it, LT_Build() will pass
  86. *        "LAMN_Handle,<Handle>" in for you, so any additional tags
  87. *        specifying screen, fonts, etc. will be overridden. If a menu
  88. *        could be created, it will be attached to the window.
  89. *        LT_DeleteHandle() will then later automatically dispose of the
  90. *        menu. Please note that the window may fail to open due to the
  91. *        menu layout going wrong. Separate calls to LT_NewMenuTagList()
  92. *        and LT_Build() may be a better approach since it is easier to
  93. *        find out which process went wrong. You will find a pointer to the
  94. *        menu attached to the LayoutHandle in LayoutHandle->Menu. Please note
  95. *        that this entry only exists in LayoutHandles created by
  96. *        gtlayout.library v13 or higher. (V13)
  97. *
  98. *            NOTE: This tag effectively overrides LAWN_Menu and has
  99. *                  precedence over LAWN_MenuTemplate.
  100. *
  101. *    LAWN_UserPort (struct MsgPort *) - The MsgPort to use as the
  102. *        window user port. The MsgPort will be attached using the
  103. *        common ModifyIDCMP() method, closing the window will
  104. *        first remove and reply all pending messages at this port.
  105. *
  106. *    LAWN_Left (LONG) - The left edge position the window is to use.
  107. *        This effectively overrides any horizontal alignment flags.
  108. *
  109. *            NOTE: the code may choose to ignore this value if it finds
  110. *                that the window will not fit onto the screen unless
  111. *                the left edge position is changed.
  112. *
  113. *    LAWN_Top (LONG) - The top edge position the window is to use.
  114. *        This effectively overrides any vertical alignment flags.
  115. *
  116. *            NOTE: the code may choose to ignore this value if it finds
  117. *                that the window will not fit onto the screen unless
  118. *                the top edge position is changed.
  119. *
  120. *    LAWN_Zoom (BOOL) - Adds a zoom gadget to the window. Clicking
  121. *        on this gadget will cause the window to shrink/zoom back
  122. *        to its original position. This differs from the WA_Zoom
  123. *        tag behaviour. When the window zooms back to its original
  124. *        position the gadgets are automatically refreshed.
  125. *        Default: FALSE
  126. *
  127. *    LAWN_MaxPen (LONG) - The maximum rendering pen index your code
  128. *        will use. Since you are -- with some restrictions -- allowed
  129. *        to render into the window created you may want to avoid
  130. *        silly side effects if drawing images or other colourful
  131. *        textures which do not share the common user interface colours.
  132. *        By default the layout code will change the maximum rendering
  133. *        pen number for the window to include only the user interface
  134. *        pen colours. This can, but need not disturb your own private
  135. *        window rendering.
  136. *        Look up graphics.library/SetMaxPen for more information.
  137. *        Default: determined by looking up Screen->DrawInfo.dri_Pens
  138. *
  139. *    LAWN_BelowMouse (BOOL) - This instructs the layout routine to
  140. *        centre the window created -- if possible -- below the
  141. *        mouse pointer. This effectively ignores any left edge,
  142. *        top edge or alignment settings.
  143. *        Default: FALSE
  144. *
  145. *    LAWN_MoveToWindow (BOOL) - When the window is finally open the
  146. *        user interface code will try to make sure the entire window
  147. *        is visible on the screen, this may involve moving the
  148. *        currently visible portion of an autoscrolling screen.
  149. *        Default: TRUE
  150. *
  151. *    LAWN_AutoRefresh (BOOL) - Handle IDCMP_REFRESHWINDOW events
  152. *        automatically.
  153. *        Default: TRUE
  154. *
  155. *    LAWN_HelpHook (struct Hook *) - Hook code to invoke when the user
  156. *        presses the "Help" key. See gtlayout.h for more information.
  157. *        Default: NULL
  158. *
  159. *    LAWN_Parent (struct Window *) - Parent window to centre the child
  160. *        window in.
  161. *        Default: NULL
  162. *
  163. *    LAWN_BlockParent (BOOL) - Lock the parent window via LT_LockWindow()
  164. *        until the child window is closed.
  165. *
  166. *            NOTE: requires LAWN_Parent attribute.
  167. *
  168. *        Default: FALSE
  169. *
  170. *    LAWN_SmartZoom (BOOL) - Attach a zoom gadget to the window created.
  171. *        When in zoomed state, the window will be as small as possible,
  172. *        showing only the window title and window gadgets:
  173. *
  174. *            NOTE: this tag implies LAWN_Zoom,TRUE
  175. *
  176. *        Default: FALSE
  177. *
  178. *    LAWN_Title (STRPTR) - The window title to use. Use this tag in
  179. *        place of WA_Title or you will break the layout code.
  180. *        Default: no title
  181. *
  182. *    LAWN_Bounds (struct IBox *) - Bounds to centre the window in.
  183. *        Default: NULL
  184. *
  185. *    LAWN_ExtraWidth (LONG) - Extra width to add into the calculation
  186. *        when opening the window.
  187. *        Default: 0
  188. *
  189. *    LAWN_ExtraHeight (LONG) - Extra height to add into the calculation
  190. *        when opening the window.
  191. *        Default: 0
  192. *
  193. *    LAWN_IDCMP (ULONG) - Use this tag in place of WA_IDCMP or you
  194. *        will break the object handling code.
  195. *
  196. *    LAWN_AlignWindow (UWORD) - Alignment information for the window, must
  197. *        be a mask made from the following bit values:
  198. *
  199. *            ALIGNF_RIGHT - Align to screen right edge
  200. *            ALIGNF_LEFT - Align to screen left edge
  201. *            ALIGNF_TOP - Align to screen top edge
  202. *            ALIGNF_BOTTOM - Align to screen bottom edge
  203. *
  204. *        Unless forbidden (such as by passing ALIGNF_RIGHT|ALIGNF_TOP)
  205. *        the window will be centered horizontally and/or vertically.
  206. *
  207. *    LAWN_FlushLeft (BOOL) - Add no horizontal space surrounding the
  208. *        objects the windows will hold. (V10)
  209. *
  210. *    LAWN_FlushTop (BOOL) - Add no vertical space surrounding the
  211. *        objects the windows will hold. (V10)
  212. *
  213. *    LAWN_Show (BOOL) - Make the window visible when it is opened;
  214. *        this may involve depth-arranging screens. (V10)
  215. *           Default: FALSE
  216. *
  217. *    LAWN_NoInitialRefresh (BOOL) - If set to TRUE, adds the
  218. *        gadgets, but does not draw the window imagery. You need
  219. *        to draw them later by calling gtlayout.library/LT_Refresh.
  220. *        Default: FALSE
  221. *
  222. *    LAWN_LimitWidth (UWORD) - Limit the width of the window to this
  223. *        value. (V35)
  224. *
  225. *    LAWN_LimitHeight (UWORD) - Limit the height of the window to this
  226. *        value. (V35)
  227. *
  228. *   RESULT
  229. *    Window - Pointer to a Window structure.
  230. *
  231. *   SEE ALSO
  232. *       gtlayout.library/LT_Refresh
  233. *       intuition.library/OpenWindow
  234. *       intuition.library/OpenWindowTagList
  235. *
  236. ******************************************************************************
  237. *
  238. */
  239.  
  240. struct Window * LIBENT
  241. LT_BuildA(REG(a0) LayoutHandle *handle,REG(a1) struct TagItem *TagParams)
  242. {
  243.     ULONG             OpenWindowTag;
  244.     LONG             left, top, width, height;
  245.     LONG             OldLeft,OldTop,OldRight,OldBottom;
  246.     struct IBox         newBounds;
  247.     struct Menu        *menu;
  248.     struct TagItem    *item;
  249.     LONG             placeLeft;
  250.     LONG             placeTop;
  251.     struct IBox         zoomBox;
  252.     struct IBox        *zoom;
  253.     struct TextFont *font;
  254.     struct TagItem    *NewTags,*Tags;
  255.     struct Window    *Parent;
  256.     STRPTR             title;
  257.     struct IBox        *bounds;
  258.     LONG             extraWidth,
  259.                      extraHeight;
  260.     ULONG             IDCMP;
  261.     LONG             align;
  262.     LONG             MinX,
  263.                      MinY,
  264.                      MaxX,
  265.                      MaxY;
  266.     ULONG             BorderBottom,
  267.                      BorderRight;
  268.     struct Menu        *LocalMenu;
  269.     struct TagItem    *LocalMenuTags;
  270.     struct NewMenu    *LocalMenuTemplate;
  271.     BOOL             SizeGadget,
  272.                      SizeBRight,
  273.                      SizeBBottom;
  274.     BOOL              BlockParent,
  275.                      SmartZoom,
  276.                      MakeVisible;
  277.     BOOL             DontRefresh;
  278.     struct TagItem    *TagList;
  279.     WORD             WithinCounter;
  280.  
  281.     if(!handle)
  282.         return(NULL);
  283.  
  284.     menu                = NULL;
  285.     NewTags                = NULL;
  286.     Parent                = handle->Parent;
  287.     title                = NULL;
  288.     bounds                 = NULL;
  289.     extraWidth            = 0,
  290.     extraHeight            = 0;
  291.     IDCMP                = NULL;
  292.     align                = 0;
  293.     LocalMenu            = NULL;
  294.     LocalMenuTags        = NULL;
  295.     LocalMenuTemplate    = NULL;
  296.     SizeGadget            = FALSE,
  297.     SizeBRight            = FALSE,
  298.     SizeBBottom            = FALSE;
  299.     BlockParent            = handle->BlockParent,
  300.     SmartZoom            = FALSE,
  301.     MakeVisible            = FALSE;
  302.     DontRefresh            = FALSE;
  303.  
  304.     WithinCounter = 0;
  305.  
  306.     TagList = (struct TagItem *)TagParams;
  307.     while(item = NextTagItem(&TagList))
  308.     {
  309.         switch(item->ti_Tag)
  310.         {
  311.             case LAWN_LimitWidth:
  312.  
  313.                 WithinCounter |= 1;
  314.                 newBounds.Width = item->ti_Data;
  315.                 break;
  316.  
  317.             case LAWN_LimitHeight:
  318.  
  319.                 WithinCounter |= 2;
  320.                 newBounds.Height = item->ti_Data;
  321.                 break;
  322.  
  323.             case LAWN_NoInitialRefresh:
  324.  
  325.                 DontRefresh = item->ti_Data;
  326.                 break;
  327.  
  328.             case LAWN_MenuTemplate:
  329.  
  330.                 LocalMenuTemplate = (struct NewMenu *)item->ti_Data;
  331.                 break;
  332.  
  333.             case LAWN_MenuTags:
  334.  
  335.                 LocalMenuTags = (struct TagItem *)item->ti_Data;
  336.                 break;
  337.  
  338.             case LAWN_FlushLeft:
  339.  
  340.                 handle->FlushLeft = item->ti_Data;
  341.                 break;
  342.  
  343.             case LAWN_FlushTop:
  344.  
  345.                 handle->FlushTop = item->ti_Data;
  346.                 break;
  347.  
  348.             case LAWN_TitleText:
  349.  
  350.                 title = (STRPTR)item->ti_Data;
  351.                 break;
  352.  
  353.             case LAWN_TitleID:
  354.  
  355.                 if(!handle->LocaleHook)
  356.                     return(NULL);
  357.                 else
  358.                     title = (STRPTR)CallHookPkt(handle->LocaleHook,handle,(APTR)item->ti_Data);
  359.  
  360.                 break;
  361.  
  362.             case LAWN_Bounds:
  363.  
  364.                 bounds = (struct IBox *)item->ti_Data;
  365.                 break;
  366.  
  367.             case LAWN_ExtraWidth:
  368.  
  369.                 extraWidth = item->ti_Data;
  370.                 break;
  371.  
  372.             case LAWN_ExtraHeight:
  373.  
  374.                 extraHeight = item->ti_Data;
  375.                 break;
  376.  
  377.             case LAWN_IDCMP:
  378.  
  379.                 IDCMP = item->ti_Data;
  380.                 break;
  381.  
  382.             case LAWN_AlignWindow:
  383.  
  384.                 align = item->ti_Data;
  385.                 break;
  386.         }
  387.     }
  388.  
  389.     if(!bounds && WithinCounter == 3)
  390.     {
  391.         UWORD width,height;
  392.  
  393.         width = newBounds.Width;
  394.         height = newBounds.Height;
  395.  
  396.         LTP_GetDisplayClip(handle->Screen,&newBounds.Left,&newBounds.Top,&newBounds.Width,&newBounds.Height);
  397.         bounds = &newBounds;
  398.  
  399.         bounds->Width = width;
  400.         bounds->Height = height;
  401.     }
  402.  
  403. #ifdef DO_MENUS
  404.     if(LocalMenuTags)
  405.     {
  406.         if(LocalMenu = LT_NewMenuTags(LAMN_Handle,handle,TAG_MORE,LocalMenuTags))
  407.         {
  408.             menu = LocalMenu;
  409.             handle->IDCMP |= IDCMP_MENUPICK;
  410.         }
  411.         else
  412.             return(NULL);
  413.     }
  414.     else
  415.     {
  416.         if(LocalMenuTemplate)
  417.         {
  418.             if(LocalMenu = LT_NewMenuTemplate(handle->Screen,handle->TextAttr,handle->AmigaGlyph,handle->CheckGlyph,NULL,LocalMenuTemplate))
  419.             {
  420.                 menu = LocalMenu;
  421.                 handle->IDCMP |= IDCMP_MENUPICK;
  422.             }
  423.             else
  424.                 return(NULL);
  425.         }
  426.     }
  427. #endif    /* DO_MENUS */
  428.  
  429.     if(!bounds)
  430.     {
  431.         LTP_GetDisplayClip(handle->Screen,&newBounds.Left,&newBounds.Top,&newBounds.Width,&newBounds.Height);
  432.  
  433.         bounds = &newBounds;
  434.     }
  435.  
  436.     left = handle->Screen->WBorLeft;
  437.  
  438.     if(title)
  439.         top = handle->Screen->WBorTop + handle->Screen->Font->ta_YSize + 1;
  440.     else
  441.         top = handle->Screen->WBorTop;
  442.  
  443.     BorderRight        = handle->Screen->WBorRight;
  444.     BorderBottom    = handle->Screen->WBorBottom;
  445.  
  446.     if(handle->ResizeView)
  447.     {
  448.         if(handle->ResizeView->Special.List.ResizeY)
  449.             BorderBottom = LTP_GetSizeHeight(handle);
  450.         else
  451.         {
  452.             if(handle->ResizeView->Special.List.ResizeX)
  453.                 BorderRight = LTP_GetSizeWidth(handle);
  454.         }
  455.     }
  456.  
  457.     OldLeft        = left;
  458.     OldRight    = BorderRight;
  459.     OldTop        = top;
  460.     OldBottom    = BorderBottom;
  461.  
  462.     if(!handle->FlushLeft)
  463.     {
  464.         left        += handle->InterWidth;
  465.         BorderRight    += handle->InterWidth;
  466.     }
  467.  
  468.     if(!handle->FlushTop)
  469.     {
  470.         top                += handle->InterHeight;
  471.         BorderBottom    += handle->InterHeight;
  472.     }
  473.  
  474.     LTP_CreateGadgets(handle,bounds,left,top,left + BorderRight,top + BorderBottom);
  475.  
  476.     if(handle->Failed)
  477.         return(NULL);
  478.  
  479.         // In case the font got changed we'll have to redo it all again.
  480.         // Just to be sure, we do it all over again.
  481.  
  482.     left            = OldLeft;
  483.     BorderRight        = OldRight;
  484.     top                = OldTop;
  485.     BorderBottom    = OldBottom;
  486.  
  487.     if(!handle->FlushLeft)
  488.     {
  489.         left        += handle->InterWidth;
  490.         BorderRight    += handle->InterWidth;
  491.     }
  492.  
  493.     if(!handle->FlushTop)
  494.     {
  495.         top                += handle->InterHeight;
  496.         BorderBottom    += handle->InterHeight;
  497.     }
  498.  
  499.     width    = left + handle->TopGroup->Width + BorderRight;
  500.     height    = top + handle->TopGroup->Height + BorderBottom;
  501.  
  502.     if(handle->ResizeView)
  503.     {
  504.         LONG GlyphWidth,GlyphHeight;
  505.  
  506.         MaxX = MinX = width;
  507.         MaxY = MinY = height;
  508.  
  509.         if(handle->ResizeView->Special.List.ResizeX)
  510.             MaxX = handle->Screen->Width;
  511.  
  512.         if(handle->ResizeView->Special.List.ResizeY)
  513.         {
  514.             MaxY = handle->Screen->Height;
  515.  
  516.             SizeBBottom = TRUE;
  517.         }
  518.         else
  519.             SizeBRight = TRUE;
  520.  
  521.         SizeGadget = TRUE;
  522.  
  523.         if(handle->ResizeView->Special.List.TextAttr)
  524.         {
  525.             GlyphWidth    = handle->ResizeView->Special.List.FixedGlyphWidth;
  526.             GlyphHeight    = handle->ResizeView->Special.List.FixedGlyphHeight;
  527.         }
  528.         else
  529.         {
  530.             GlyphWidth    = handle->GlyphWidth;
  531.             GlyphHeight    = handle->GlyphHeight;
  532.         }
  533.  
  534.         if(handle->ResizeView->Special.List.MinChars && handle->ResizeView->Special.List.MinChars < handle->ResizeView->Chars)
  535.             MinX -= GlyphWidth * (handle->ResizeView->Chars - handle->ResizeView->Special.List.MinChars);
  536.  
  537.         if(handle->ResizeView->Special.List.MinLines && handle->ResizeView->Special.List.MinChars < handle->ResizeView->Lines)
  538.             MinY -= GlyphHeight * (handle->ResizeView->Lines - handle->ResizeView->Special.List.MinLines);
  539.     }
  540.     else
  541.     {
  542.         MaxX = MinX = width;
  543.         MaxY = MinY = height;
  544.     }
  545.  
  546.     if(align & ALIGNF_LEFT)
  547.         placeLeft = 0;
  548.     else
  549.     {
  550.         if(align & ALIGNF_RIGHT)
  551.             placeLeft = bounds->Width - (width + extraWidth);
  552.         else
  553.             placeLeft = (bounds->Width - (width + extraWidth)) / 2;
  554.     }
  555.  
  556.     if(align & ALIGNF_TOP)
  557.         placeTop = 0;
  558.     else
  559.     {
  560.         if(align & ALIGNF_BOTTOM)
  561.             placeTop = bounds->Height - (height + extraHeight);
  562.         else
  563.             placeTop = (bounds->Height - (height + extraHeight)) / 2;
  564.     }
  565.  
  566.     if(align & ALIGNF_EXTRA_LEFT)
  567.         placeLeft += extraWidth;
  568.     else
  569.     {
  570.         if(!(align & ALIGNF_EXTRA_RIGHT))
  571.             placeLeft += extraWidth / 2;
  572.     }
  573.  
  574.     if(align & ALIGNF_EXTRA_TOP)
  575.         placeTop += extraHeight;
  576.     else
  577.     {
  578.         if(!(align & ALIGNF_EXTRA_BOTTOM))
  579.             placeTop += extraHeight / 2;
  580.     }
  581.  
  582.     placeLeft    += bounds->Left;
  583.     placeTop    += bounds->Top;
  584.  
  585.     if(placeLeft < 0)
  586.         placeLeft = 0;
  587.  
  588.     if(placeTop < 0)
  589.         placeTop = 0;
  590.  
  591.     zoom = NULL;
  592.  
  593.     handle->AutoRefresh = TRUE;
  594.  
  595. #ifdef DO_CLONING
  596.     if(handle->CloneExtra)
  597.     {
  598.         placeLeft    = 0;
  599.         placeTop    = handle->CloneExtra->Screen->BarHeight + 1;
  600.  
  601.         zoomBox.Left    = placeLeft;
  602.         zoomBox.Top        = placeTop;
  603.     }
  604. #endif    /* DO_CLONING */
  605.  
  606.     TagList = (struct TagItem *)TagParams;
  607.  
  608.     while(item = NextTagItem(&TagList))
  609.     {
  610.         switch((ULONG)item->ti_Tag)
  611.         {
  612.             case LA_Menu:
  613.  
  614.                 if(!menu)
  615.                 {
  616.                     handle->IDCMP |= IDCMP_MENUPICK;
  617.  
  618.                     menu = (struct Menu *)item->ti_Data;
  619.                 }
  620.  
  621.                 break;
  622.  
  623.             case LAWN_SmartZoom:
  624.  
  625.                 if(!(SmartZoom = item->ti_Data))
  626.                     break;
  627.  
  628.             case LAWN_Zoom:
  629.  
  630.                 if(item->ti_Data)
  631.                 {
  632.                     if(title && SmartZoom)
  633.                     {
  634.                         STATIC UWORD WhichTable[3] =
  635.                         {
  636.                             CLOSEIMAGE,
  637.                             ZOOMIMAGE,
  638.                             DEPTHIMAGE
  639.                         };
  640.  
  641.                         LONG     Size = 0,i;
  642.                         LONG     SizeType;
  643.                         Object    *Image;
  644.                         BOOL     GotIt = TRUE;
  645.  
  646.                         if(handle->Screen->Flags & SCREENHIRES)
  647.                             SizeType = SYSISIZE_MEDRES;
  648.                         else
  649.                             SizeType = SYSISIZE_LOWRES;
  650.  
  651.                         for(i = 0 ; i < 3 ; i++)
  652.                         {
  653.                             if(Image = NewObject(NULL,SYSICLASS,
  654.                                 SYSIA_Size,        SizeType,
  655.                                 SYSIA_Which,    WhichTable[i],
  656.                                 SYSIA_DrawInfo, handle->DrawInfo,
  657.                             TAG_DONE))
  658.                             {
  659.                                 ULONG Width;
  660.  
  661.                                 GetAttr(IA_Width,Image,&Width);
  662.  
  663.                                 Size += Width;
  664.  
  665.                                 DisposeObject(Image);
  666.                             }
  667.                             else
  668.                                 GotIt = FALSE;
  669.                         }
  670.  
  671.                         if(GotIt)
  672.                         {
  673.                             Size += 8 + TextLength(&handle->Screen->RastPort,title,strlen(title)) + 8;
  674.  
  675.                             zoomBox.Width = Size;
  676.                         }
  677.                         else
  678.                             zoomBox.Width = width;
  679.                     }
  680.                     else
  681.                         zoomBox.Width = width;
  682.  
  683.                     if(V39)
  684.                     {
  685.                         zoomBox.Left    = -1;
  686.                         zoomBox.Top        = -1;
  687.                     }
  688.                     else
  689.                     {
  690.                         zoomBox.Left    = placeLeft;
  691.                         zoomBox.Top        = placeTop;
  692.                     }
  693.  
  694.                     zoomBox.Height = handle->Screen->WBorTop + handle->Screen->Font->ta_YSize + 1;
  695.  
  696.                     zoom = &zoomBox;
  697.                 }
  698.  
  699.                 break;
  700.  
  701.             case LAWN_UserPort:
  702.  
  703.                 handle->MsgPort = (struct MsgPort *)item->ti_Data;
  704.                 break;
  705.  
  706.             case LAWN_HelpHook:
  707.  
  708.                 handle->HelpHook = (struct Hook *)item->ti_Data;
  709.                 break;
  710.  
  711.             case LAWN_Parent:
  712.  
  713.                 Parent = (struct Window *)item->ti_Data;
  714.                 break;
  715.  
  716.             case LAWN_BlockParent:
  717.  
  718.                 BlockParent = item->ti_Data;
  719.                 break;
  720.  
  721.             case LAWN_BelowMouse:
  722.  
  723.                 if((placeLeft = handle->Screen->MouseX - (width / 2)) < 0)
  724.                     placeLeft = 0;
  725.  
  726.                 if((placeTop = handle->Screen->MouseY - (height / 2)) < 0)
  727.                     placeTop = 0;
  728.  
  729.                 break;
  730.  
  731.             case LAWN_MaxPen:
  732.  
  733.                 handle->MaxPen = (LONG)item->ti_Data;
  734.                 break;
  735.  
  736.             case LAWN_MoveToWindow:
  737.  
  738.                 handle->MoveToWindow = (LONG)item->ti_Data;
  739.                 break;
  740.  
  741.             case LAWN_AutoRefresh:
  742.  
  743.                 handle->AutoRefresh = (LONG)item->ti_Data;
  744.                 break;
  745.  
  746.             case LAWN_Show:
  747.  
  748.                 MakeVisible = item->ti_Data;
  749.                 break;
  750.         }
  751.     }
  752.  
  753.     Tags = (struct TagItem *)TagParams;
  754.  
  755.     if(handle->BackgroundPen && !V39)
  756.     {
  757.         if(NewTags = CloneTagItems(Tags))
  758.         {
  759.             STATIC Tag Filter[] = { WA_SimpleRefresh,TAG_DONE };
  760.  
  761.             FilterTagItems(NewTags,Filter,TAGFILTER_NOT);
  762.  
  763.             Tags = NewTags;
  764.         }
  765.         else
  766.         {
  767. #ifdef DO_MENUS
  768.             LT_DisposeMenu(LocalMenu);
  769. #endif    /* DO_MENUS */
  770.             return(NULL);
  771.         }
  772.     }
  773.  
  774.     if(Parent)
  775.     {
  776.         WORD    Left,Top,Width,Height;
  777.         LONG    MoveLeft,MoveTop,WindowLeft,WindowTop,WindowWidth,WindowHeight;
  778.  
  779.         WindowLeft        = Parent->LeftEdge + Parent->BorderLeft;
  780.         WindowTop        = Parent->TopEdge + Parent->BorderTop;
  781.         WindowWidth        = Parent->Width - (Parent->BorderLeft + Parent->BorderRight);
  782.         WindowHeight    = Parent->Height - (Parent->BorderTop + Parent->BorderBottom);
  783.  
  784.         LTP_GetDisplayClip(Parent->WScreen,&Left,&Top,&Width,&Height);
  785.  
  786.         if((MoveLeft = WindowLeft + (WindowWidth - width) / 2) < 0)
  787.             MoveLeft = 0;
  788.  
  789.         if((MoveTop = WindowTop + (WindowHeight - height) / 2) < 0)
  790.             MoveTop = 0;
  791.  
  792.         if(MoveLeft < Left || MoveLeft + width > Left + Width)
  793.             MoveLeft = -1;
  794.  
  795.         if(MoveTop < Top || MoveTop + height > Top + Height)
  796.             MoveTop = -1;
  797.  
  798.         if(MoveTop != -1 && MoveLeft != -1)
  799.         {
  800.             placeLeft    = MoveLeft;
  801.             placeTop    = MoveTop;
  802.         }
  803.     }
  804.  
  805.     TagList = (struct TagItem *)TagParams;
  806.  
  807.     while(item = NextTagItem(&TagList))
  808.     {
  809.         switch((ULONG)item->ti_Tag)
  810.         {
  811.             case LAWN_Left:
  812.  
  813.                 placeLeft = item->ti_Data;
  814.                 break;
  815.  
  816.             case LAWN_Top:
  817.  
  818.                 placeTop = item->ti_Data;
  819.                 break;
  820.         }
  821.     }
  822.  
  823.     if(BlockParent && Parent)
  824.     {
  825.         LT_LockWindow(Parent);
  826.  
  827.         handle->Parent = Parent;
  828.     }
  829.  
  830.     if(SizeGadget)
  831.         zoom = NULL;
  832.  
  833.     if(handle->Screen == handle->PubScreen)
  834.         OpenWindowTag = handle->WA_ScreenTag;
  835.     else
  836.         OpenWindowTag = WA_CustomScreen;
  837.  
  838.     if(handle->Window = OpenWindowTags(NULL,
  839.         WA_Left,            placeLeft,
  840.         WA_Top,             placeTop,
  841.         WA_Width,            width,
  842.         WA_Height,            height,
  843.         WA_NewLookMenus,    TRUE,
  844.         OpenWindowTag,        handle->Screen,
  845.         WA_MinWidth,        MinX,
  846.         WA_MinHeight,        MinY,
  847.         WA_MaxWidth,        MaxX,
  848.         WA_MaxHeight,        MaxY,
  849.         WA_SizeGadget,        SizeGadget,
  850.         WA_SizeBBottom,        SizeBBottom,
  851.         WA_SizeBRight,        SizeBRight,
  852.         WA_PointerDelay,    TRUE,
  853.         WA_BusyPointer,        TRUE,
  854.  
  855.         zoom ? WA_Zoom : TAG_IGNORE,                        zoom,
  856.         !handle->MsgPort ? WA_IDCMP : TAG_IGNORE,            IDCMP_REFRESHWINDOW | IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_CHANGEWINDOW | IDCMP | handle->IDCMP,
  857.         title ? WA_Title : TAG_IGNORE,                        title,
  858.         handle->AmigaGlyph ? WA_AmigaKey : TAG_IGNORE,        handle->AmigaGlyph,
  859.         handle->CheckGlyph ? WA_Checkmark : TAG_IGNORE,        handle->CheckGlyph,
  860.         handle->BackgroundPen ? WA_BackFill : TAG_IGNORE,    &handle->BackfillHook,
  861.     TAG_MORE,Tags))
  862.     {
  863.         font = handle->RPort.Font;
  864.  
  865.         handle->RPort = *handle->Window->RPort;
  866.  
  867.         LTP_SetFont(handle,font);
  868.  
  869.         if(V39 && handle->MaxPen > 0)
  870.         {
  871.             SetMaxPen(&handle->RPort,handle->MaxPen);
  872.             SetMaxPen(handle->Window->RPort,handle->MaxPen);
  873.         }
  874.  
  875.         if(NewTags)
  876.         {
  877.             FreeTagItems(NewTags);
  878.             NewTags = NULL;
  879.         }
  880.  
  881.             // It's really that simple...
  882.  
  883.         if(DontRefresh)
  884.             LTP_AddGadgetsDontRefresh(handle);
  885.         else
  886.             LTP_AddGadgets(handle);
  887.  
  888.         handle->Window->UserData = (APTR)handle;
  889.  
  890.         if(handle->MsgPort)
  891.         {
  892.             handle->Window->UserPort = handle->MsgPort;
  893.  
  894.             if(!ModifyIDCMP(handle->Window,IDCMP_CHANGEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP | handle->IDCMP))
  895.             {
  896.                 handle->Window->UserPort = NULL;
  897.  
  898.                 return (NULL);
  899.             }
  900.         }
  901.  
  902.         if(menu)
  903.             SetMenuStrip(handle->Window,menu);
  904.  
  905.         handle->Menu = LocalMenu;
  906.  
  907.         LTP_SelectInitialActiveGadget(handle);
  908. #ifdef DO_CLONING
  909.         if(handle->CloneExtra)
  910.             ScreenToFront(handle->Window->WScreen);
  911. #endif
  912.         if(V39)
  913.             SetWindowPointerA(handle->Window,NULL);
  914.  
  915.         if(MakeVisible)
  916.             ScreenToFront(handle->Screen);
  917.  
  918.         if(handle->MoveToWindow || MakeVisible)
  919.             LTP_MoveToWindow(handle);
  920.  
  921.         if((handle->Window->Flags & WFLG_WINDOWACTIVE) && handle->ActiveString && !DontRefresh)
  922.             LT_Activate(handle,handle->ActiveString->ID);
  923.     }
  924.     else
  925.     {
  926.         if(handle->Parent)
  927.         {
  928.             LT_UnlockWindow(handle->Parent);
  929.  
  930.             handle->Parent = NULL;
  931.         }
  932.  
  933. #ifdef DO_MENUS
  934.         LT_DisposeMenu(LocalMenu);
  935. #endif    /* DO_MENUS */
  936.     }
  937.  
  938.     FreeTagItems(NewTags);
  939.  
  940.     return(handle->Window);
  941. }
  942.  
  943.  
  944. /*****************************************************************************/
  945.  
  946.  
  947. VOID
  948. LTP_SelectInitialActiveGadget(LayoutHandle *Handle)
  949. {
  950.     ObjectNode *Node;
  951.     LONG i;
  952.  
  953.     Handle->Previous = NULL;
  954.  
  955.     for(i = 0 ; i < Handle->Count ; i++)
  956.     {
  957.         if(Handle->GadgetArray[i])
  958.         {
  959.             if(GETOBJECT(Handle->GadgetArray[i],Node))
  960.             {
  961.                 if(LIKE_STRING_KIND(Node) || (Node->Type == INTEGER_KIND))
  962.                 {
  963.                     Handle->Previous = Handle->GadgetArray[i];
  964.                     break;
  965.                 }
  966.             }
  967.         }
  968.     }
  969. }
  970.  
  971.  
  972. /*****************************************************************************/
  973.  
  974.  
  975. struct Window *
  976. LT_Layout(LayoutHandle *handle,STRPTR title,struct IBox *bounds,LONG extraWidth,LONG extraHeight,ULONG IDCMP,LONG align,...)
  977. {
  978.     struct Window *Result;
  979.     va_list VarArgs;
  980.  
  981.     va_start(VarArgs,align);
  982.  
  983.     Result = LT_Build(handle,
  984.         LAWN_Title,            title,
  985.         LAWN_Bounds,        bounds,
  986.         LAWN_ExtraWidth,    extraWidth,
  987.         LAWN_ExtraHeight,    extraHeight,
  988.         LAWN_IDCMP,            IDCMP,
  989.         LAWN_AlignWindow,    align,
  990.     TAG_MORE,(struct TagItem *)VarArgs);
  991.  
  992.     va_end(VarArgs);
  993.  
  994.     return(Result);
  995. }
  996.  
  997.  
  998. /*****************************************************************************/
  999.  
  1000.  
  1001. struct Window * LIBENT
  1002. LT_LayoutA(REG(a0) LayoutHandle *handle,REG(a1) STRPTR title,REG(a2) struct IBox *bounds,REG(d0) LONG extraWidth,REG(d1) LONG extraHeight,REG(d2) ULONG IDCMP,REG(d3) LONG align,REG(a3) struct TagItem *TagParams)
  1003. {
  1004.     struct Window *Result;
  1005.  
  1006.     Result = LT_Build(handle,
  1007.         LAWN_Title,            title,
  1008.         LAWN_Bounds,        bounds,
  1009.         LAWN_ExtraWidth,    extraWidth,
  1010.         LAWN_ExtraHeight,    extraHeight,
  1011.         LAWN_IDCMP,            IDCMP,
  1012.         LAWN_AlignWindow,    align,
  1013.     TAG_MORE,TagParams);
  1014.  
  1015.     return(Result);
  1016. }
  1017.  
  1018.  
  1019. /*****************************************************************************/
  1020.  
  1021.  
  1022. struct Window *
  1023. LT_Build(LayoutHandle *Handle,...)
  1024. {
  1025.     struct Window *Result;
  1026.     va_list VarArgs;
  1027.  
  1028.     va_start(VarArgs,Handle);
  1029.     Result = LT_BuildA(Handle,(struct TagItem *)VarArgs);
  1030.     va_end(VarArgs);
  1031.  
  1032.     return(Result);
  1033. }
  1034.